

#include "modules/video_capture/ohos/device_info_ohos.h"

#include "modules/video_capture/video_capture_config.h"
#include "rtc_base/logging.h"
#include "rtc_base/string_utils.h"

namespace webrtc {
namespace videocapturemodule {

// static
DeviceInfoOhos* DeviceInfoOhos::Create() {
  DeviceInfoOhos* ohos_info = new DeviceInfoOhos();
  if (!ohos_info || ohos_info->Init() != 0) {
    delete ohos_info;
    ohos_info = nullptr;
  }
  return ohos_info;
}


DeviceInfoOhos::DeviceInfoOhos() {
}

DeviceInfoOhos::~DeviceInfoOhos() {
}

int32_t DeviceInfoOhos::Init() {
  Camera_ErrorCode ret;
  if (camera_manager_ == nullptr) {
    ret = OH_Camera_GetCameraManager(&camera_manager_);
    if (camera_manager_ == nullptr || ret != CAMERA_OK) {
        RTC_LOG(LS_ERROR) << "Open OH_Camera_GetCameraManager failed! ret: " << ret;
        return -1;
    }
  }
  inited_ = true;
  return 0;
}

uint32_t DeviceInfoOhos::NumberOfDevices() {
  MutexLock lock(&_apiLock);
  if (!inited_) { 
    return 0; 
  }
  cameras_ = nullptr;
  cameras_size_ = 0;
  Camera_ErrorCode ret = OH_CameraManager_GetSupportedCameras(camera_manager_, &cameras_, &cameras_size_);
  if(cameras_ == nullptr || ret != CAMERA_OK || cameras_size_ <= 0) {
    RTC_LOG(LS_ERROR) << "OH_CameraManager_GetSupportedCameras failed! ret: " << ret;
    cameras_ = nullptr;
    cameras_size_ = 0;
    return 0;
  }
  for (int index = 0; index < cameras_size_; index++) {
    RTC_LOG(LS_INFO) << "cameraId: " << cameras_[index].cameraId << " ,cameraPosition: " << cameras_[index].cameraPosition
                        << " ,cameraType: " << cameras_[index].cameraType << " ,connectionType: " << cameras_[index].connectionType;
  }
  return cameras_size_;
}

int32_t DeviceInfoOhos::GetDeviceName(uint32_t deviceNumber,
                                    char* deviceNameUTF8,
                                    uint32_t deviceNameLength,
                                    char* deviceUniqueIdUTF8,
                                    uint32_t deviceUniqueIdUTF8Length,
                                    char* productUniqueIdUTF8,
                                    uint32_t productUniqueIdUTF8Length) {
  MutexLock lock(&_apiLock);
  if (!inited_) { 
    return -1; 
  }

  if (cameras_ == nullptr || cameras_size_ <= 0) {
    if (NumberOfDevices() <= 0) {
      return -1;
    }
  }

  Camera_Position target_position = deviceNumber ? CAMERA_POSITION_FRONT : CAMERA_POSITION_BACK;
  if (cameras_ != nullptr && cameras_size_ > 0) {
    for (uint32_t index = 0; index < cameras_size_; index++) {
      if(cameras_[index].cameraPosition == target_position) {
        // camera_dev_index_ = index;
        if (deviceNameUTF8 && deviceNameLength > 0) {
          rtc::strcpyn(deviceNameUTF8, deviceNameLength, cameras_[index].cameraId);
        }
        if (deviceUniqueIdUTF8 && deviceUniqueIdUTF8Length > 0) {
          rtc::strcpyn(deviceUniqueIdUTF8, deviceUniqueIdUTF8Length, cameras_[index].cameraId);
        }
        RTC_LOG(LS_INFO) << "cameraId: " << cameras_[index].cameraId << " ,cameraPosition: " << cameras_[index].cameraPosition
                          << " ,cameraType: " << cameras_[index].cameraType << " ,connectionType: " << cameras_[index].connectionType;        
        break;
      }
    }
  }
  return -1;
}

int32_t DeviceInfoOhos::GetOrientation(const char* deviceUniqueIdUTF8,
                                       VideoRotation& orientation) {
  orientation = kVideoRotation_0;

  const int32_t deviceUniqueIdUTF8Length =
      (int32_t)strlen((char*)deviceUniqueIdUTF8);
  if (deviceUniqueIdUTF8Length >= kVideoCaptureUniqueNameLength) {
    RTC_LOG(LS_INFO) << "GetOrientation Device name too long";
    return -1;
  }

  uint32_t camera_orientation = -1;
  if (cameras_ != nullptr && cameras_size_ > 0) {
    for (uint32_t index = 0; index < cameras_size_; index++) {
      if(strcmp(cameras_[index].cameraId, deviceUniqueIdUTF8) == 0) {
        Camera_ErrorCode ret = OH_CameraDevice_GetCameraOrientation(&cameras_[index], &camera_orientation);
        if (ret != CAMERA_OK) {
          RTC_LOG(LS_ERROR) << "GetOrientation OH_CameraDevice_GetCameraOrientation failed! ret: " << ret;
          return -1;
        }
        if (camera_orientation == 0) {
          orientation = kVideoRotation_0;
        } else if (camera_orientation == 90) {
          orientation = kVideoRotation_90;
        } else if (camera_orientation == 180) {
          orientation = kVideoRotation_180;
        } else if (camera_orientation == 270) {
          orientation = kVideoRotation_270;
        }
      }
    }
  }
  if (camera_orientation >= 0) {
    return 0;
  }
  return -1;
}

int32_t DeviceInfoOhos::CreateCapabilityMap(const char* deviceUniqueIdUTF8)

{
  // Reset old capability list
  _captureCapabilities.clear();

  const int32_t deviceUniqueIdUTF8Length =
      (int32_t)strlen((char*)deviceUniqueIdUTF8);
  if (deviceUniqueIdUTF8Length >= kVideoCaptureUniqueNameLength) {
    RTC_LOG(LS_INFO) << "Device name too long";
    return -1;
  }
  RTC_LOG(LS_INFO) << "CreateCapabilityMap called for device "
                   << deviceUniqueIdUTF8;

  if (cameras_ != nullptr && cameras_size_ > 0) {
    for (uint32_t index = 0; index < cameras_size_; index++) {
      if(strcmp(cameras_[index].cameraId, deviceUniqueIdUTF8) == 0) {
        Camera_OutputCapability* cameraOutputCapability;
        Camera_ErrorCode ret = OH_CameraManager_GetSupportedCameraOutputCapability(camera_manager_, &cameras_[index], &cameraOutputCapability);
        if(cameraOutputCapability == nullptr || ret != CAMERA_OK) {
          RTC_LOG(LS_ERROR) << "OH_CameraManager_GetSupportedCameraOutputCapability failed! ret: " << ret;
          continue;
        }
        if(cameraOutputCapability->previewProfilesSize <= 0) {
          RTC_LOG(LS_ERROR) << "previewProfilesSize <= 0";    
          continue;
        }
        for (uint32_t i = 0; i < cameraOutputCapability->previewProfilesSize; ++i) {
          Camera_Profile* profile = cameraOutputCapability->previewProfiles[i];
          VideoCaptureCapability capability;
          capability.width = profile->size.width;
          capability.height = profile->size.height;

          if (profile->format == CAMERA_FORMAT_RGBA_8888) {
            capability.videoType = VideoType::kARGB;
          } else if (profile->format == CAMERA_FORMAT_YUV_420_SP) {
            capability.videoType = VideoType::kI420;
          } else if (profile->format == CAMERA_FORMAT_JPEG) {
            capability.videoType = VideoType::kI420;
          // } else if (profile->format == CAMERA_FORMAT_YCBCR_P010) {
          //   capability.videoType = VideoType::kYUY2;
          // } else if (profile->format == CAMERA_FORMAT_YCRCB_P010) {
          //   capability.videoType = VideoType::kYV12;
          }
          _captureCapabilities.push_back(capability);
        }

      }
    }
  }

  // Store the new used device name
  _lastUsedDeviceNameLength = deviceUniqueIdUTF8Length;
  _lastUsedDeviceName =
      (char*)realloc(_lastUsedDeviceName, _lastUsedDeviceNameLength + 1);
  memcpy(_lastUsedDeviceName, deviceUniqueIdUTF8,
         _lastUsedDeviceNameLength + 1);
  RTC_LOG(LS_INFO) << "CreateCapabilityMap " << _captureCapabilities.size();

  return static_cast<int32_t>(_captureCapabilities.size());
}

int32_t DeviceInfoOhos::DisplayCaptureSettingsDialogBox(
    const char* /*deviceUniqueIdUTF8*/,
    const char* /*dialogTitleUTF8*/,
    void* /*parentWindow*/,
    uint32_t /*positionX*/,
    uint32_t /*positionY*/) {
  return -1;
}

}  // namespace videocapturemodule
}  // namespace webrtc